package com.sunny.blog.service.impl;

import cn.hutool.core.collection.IterUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sunny.blog.common.entity.MessageConst;
import com.sunny.blog.common.entity.ResultCode;
import com.sunny.blog.common.entity.SysConstant;
import com.sunny.blog.mapper.*;
import com.sunny.blog.pojo.*;
import com.sunny.blog.service.BlogInfoService;
import com.sunny.blog.service.OpenApiService;
import com.sunny.blog.service.SmsSendService;
import com.sunny.blog.service.UserInfoService;
import com.sunny.blog.util.AesUtil;
import com.sunny.blog.util.CommonUtil;
import com.taobao.api.ApiException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: BlogInfoServiceImpl
 * @Description:
 * @Author: sunt
 * @Date: 2020/4/14 14:12
 * @Version 1.0
 **/
@Service
@Slf4j
public class BlogInfoServiceImpl implements BlogInfoService {


    @Value("${baidu.api_key}")
    private String apiKey;
    @Value("${baidu.secret_key}")
    private String securetKey;
    @Value("${baidu.auth_url}")
    private String authUrl;
    @Value("${baidu.text_censor}")
    private String textCensor;

    @Autowired
    private BlogInfoMapper blogInfoMapper;
    @Autowired
    private BlogTypeMapper blogTypeMapper;
    @Autowired
    private BlogTagMapper blogTagMapper;
    @Autowired
    private TagResBlogMapper tagResBlogMapper;
    @Autowired
    private CommonBlogMapper commonBlogMapper;
    @Autowired
    private BlogNoticeMapper noticeMapper;
    @Autowired
    private BlogCommentMapper blogCommentMapper;
    @Autowired
    private BlogLinkMapper blogLinkMapper;
    @Autowired
    private SmsSendService smsSendService;
    @Autowired
    private BlogBannerMapper blogBannerMapper;
    @Autowired
    private BlogReplyMapper blogReplyMapper;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private OpenApiService openApiService;

    @Override
    @Transactional
    public void insertBlog(BlogInfoBean blogInfoBean) {
        //补全数据
        String htmlContent = CommonUtil.removeTag(blogInfoBean.getContent()); //移除标签内容
        String blogId = CommonUtil.genId();
        blogInfoBean.setId(blogId);
        blogInfoBean.setUserId("20200414666L");
        blogInfoBean.setSummary(StrUtil.sub(htmlContent,0,65) + "...");
        blogInfoBean.setKeyWord(StrUtil.sub(htmlContent,0,100));
        blogInfoBean.setBrowseNum(RandomUtil.randomInt(100));
        blogInfoBean.setCommentNum(0);
        blogInfoBean.setReleaseDate(DateUtil.date());
        blogInfoBean.setIsShow(MessageConst.ENABLED);
        log.info("------>add blog...");
        blogInfoMapper.insert(blogInfoBean);
        log.info("----->add tag_res_blog...");
        insertBatchResTag(blogInfoBean.getTagIds(),blogId);
        String site = "https://www.sunnyblog.top/detail.html?id=" + blogId;
        openApiService.baiduPush(site);
    }

    @Override
    @Transactional
    @CacheEvict(cacheNames = SysConstant.PERMANENT_CACHE,key ="#blogInfoBean.id",beforeInvocation = true)
    public void updateBlog(BlogInfoBean blogInfoBean) {
        QueryWrapper queryWrapper = new QueryWrapper();
        String blogId = blogInfoBean.getId();
        queryWrapper.eq("ID",blogId);
        //标签信息先删除再新增
        log.info("del tag_res_blog:");
        QueryWrapper<TagResBlogBean> tagWraper = new QueryWrapper<TagResBlogBean>();
        tagWraper.eq("BLOG_ID",blogId);
        tagResBlogMapper.delete(tagWraper);
        log.info("insert tag_res_blog...");
        insertBatchResTag(blogInfoBean.getTagIds(),blogId);
        log.info("update_blog...");
        blogInfoMapper.update(blogInfoBean,queryWrapper);

        String site = "https://www.sunnyblog.top/detail.html?id=" + blogId;
        openApiService.baiduPush(site);
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_TYPE_CACHE,unless = "#result == null")
    public List<BlogTypeBean> queryBlogTypeList() {
        QueryWrapper<BlogTypeBean> queryWrapper = new QueryWrapper<BlogTypeBean>();
        queryWrapper.eq("IS_ENABLE",MessageConst.ENABLED);
        queryWrapper.orderByDesc("TYPE_ORDER");
        return blogTypeMapper.selectList(queryWrapper);
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_TAG_CACHE,unless = "#result == null")
    public List<BlogTagBean> queryBlogTagList() {
        QueryWrapper<BlogTagBean> queryWrapper = new QueryWrapper<BlogTagBean>();
        queryWrapper.eq("TAG_STATE",MessageConst.ENABLED);
        return blogTagMapper.selectList(queryWrapper);
    }

    @Override
    @Cacheable(value = SysConstant.BUSINESS_CACHE,key = "#blogBean",unless = "#result == null")
    public IPage<BlogInfoBean> queryBlogPage(QueryBlogBean blogBean) {
        Page<BlogInfoBean> page = new Page<>(blogBean.getCurrentPage(), blogBean.getPageSize());
        return page.setRecords(commonBlogMapper.queryBlogList(page, blogBean));
    }

    @Override
    @Cacheable(value = SysConstant.PERMANENT_CACHE,key = "#blogId",unless = "#result == null")
    public List<BlogInfoBean> queryBlogDetail(String blogId) {
        QueryWrapper<BlogInfoBean> queryWrapper = new QueryWrapper<BlogInfoBean>();
        queryWrapper.eq("id",blogId);
        List<BlogInfoBean> blogList = blogInfoMapper.selectList(queryWrapper);
        //查询分类前端展示
        QueryWrapper<BlogTypeBean> typeWrapper = new QueryWrapper<BlogTypeBean>();
        typeWrapper.eq("TYPE_ID",blogList.get(0).getTypeId());
        BlogTypeBean blogTypeBean = blogTypeMapper.selectOne(typeWrapper);

        //查询相关标签信息(后端编辑博客标签分类使用)
        QueryWrapper<TagResBlogBean> tagWraper = new QueryWrapper<TagResBlogBean>();
        tagWraper.eq("BLOG_ID",blogId);
        List<TagResBlogBean> tagList = tagResBlogMapper.selectList(tagWraper);
        List<String> tagIds = new ArrayList<String>();
        for (TagResBlogBean tagResBlogBean : tagList) {
            String tagId = tagResBlogBean.getTagId();
            tagIds.add(tagId);
        }
        for (BlogInfoBean blogInfoBean : blogList) {
            blogInfoBean.setTagIds(tagIds);
            blogInfoBean.setTypeName(blogTypeBean.getTypeName());
        }
        return blogList;
    }

    @Transactional
    @Override
    public void updateBrowseNum(String blogId) {
        QueryWrapper<BlogInfoBean> queryWrapper = new QueryWrapper<BlogInfoBean>();
        queryWrapper.eq("id",blogId);
        BlogInfoBean blogInfoBean = blogInfoMapper.selectOne(queryWrapper);
        blogInfoBean.setBrowseNum(blogInfoBean.getBrowseNum() + 1);
        blogInfoMapper.update(blogInfoBean,queryWrapper);
    }

    @Override
    public void insertBatchResTag(List<String> tagIds,String blogId) {
        if(IterUtil.isNotEmpty(tagIds)){
            for (String tagId : tagIds) {
                TagResBlogBean tagResBlogBean = new TagResBlogBean();
                tagResBlogBean.setBlogId(blogId);
                tagResBlogBean.setTagId(tagId);
                tagResBlogMapper.insert(tagResBlogBean);
            }
        }
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_RANK_INFO_CACHE,unless = "#result == null")
    public IPage<BlogInfoBean> queryRanking() {
        Page<BlogInfoBean> pageBean = new Page<>();
        pageBean.setSize(15);
        QueryWrapper<BlogInfoBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.select("ID","TITLE");
        queryWrapper.eq("IS_SHOW",MessageConst.ENABLED);
        queryWrapper.orderByDesc("BROWSE_NUM");
        return blogInfoMapper.selectPage(pageBean, queryWrapper);
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_SIMILAR_INFO_CACHE,key = "#blogId",unless = "#result == null")
    public IPage<BlogInfoBean> querySimilar(String blogId) {
        Page<BlogInfoBean> page = new Page<>(1, 10);
        return page.setRecords(commonBlogMapper.querySimilarList(page,blogId));
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_TAG_GROUP_CACHE,unless = "#result == null")
    public List<TagGroupBean> queryTagGroupInfo() {
        return commonBlogMapper.queryTagGroupInfo();
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_TYPE_GROUP_CACHE,unless = "#result == null")
    public List<BlogTypeBean> queryBlogTypeGroupInfo() {
        return commonBlogMapper.queryBlogTypeGroupInfo();
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_NOTICE_CACHE,unless = "#result == null")
    public List<BlogNoticeBean> queryNoticeList() {
        QueryWrapper<BlogNoticeBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("IS_ENABLE",MessageConst.ENABLED);
        return noticeMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional
    public String insertBlogComment(BlogCommentBean blogCommentBean) {
        String commentId = CommonUtil.genId();
        blogCommentBean.setCommentId(commentId);
        blogCommentBean.setCommentDate(DateUtil.date());
        blogCommentBean.setCommentState(MessageConst.DISABLED);
        blogCommentMapper.insert(blogCommentBean);
        try {
            smsSendService.sendDingTextMsg("您的博客：https://www.sunnyblog.top/detail.html?id=" + blogCommentBean.getBlogId() + "，有最新的" +
                    "评论，评论时间:【"+DateUtil.formatDateTime(DateUtil.date())+"】,评论编码:【" + commentId + ",请及时登录系统处理!",null,true);
        } catch (ApiException e) {
            log.error("评论钉钉通知异常...");
            e.printStackTrace();
        }
        return commentId;
    }

    @Override
    public void updateBlogCommentCnt(String blogId) {
        QueryWrapper<BlogInfoBean> queryWrapper = new QueryWrapper<BlogInfoBean>();
        queryWrapper.eq("id",blogId);
        BlogInfoBean blogInfoBean = blogInfoMapper.selectOne(queryWrapper);
        blogInfoBean.setCommentNum(blogInfoBean.getCommentNum() + 1);
        blogInfoMapper.update(blogInfoBean,queryWrapper);
    }

    @Override
    @Transactional
    public void updateCommentState(String commentId) {
        BlogCommentBean commentBean = new BlogCommentBean();
        QueryWrapper<BlogCommentBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("COMMENT_ID",commentId);
        commentBean.setCommentState(MessageConst.ENABLED);
        blogCommentMapper.update(commentBean,queryWrapper);
    }

    @Override
    @Transactional
    public void updateCommentRemark(String commentId, String remark) {
        BlogCommentBean commentBean = new BlogCommentBean();
        QueryWrapper<BlogCommentBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("COMMENT_ID",commentId);
        //int 默认为0 这里仍然审核未通过
        commentBean.setCommentState(MessageConst.DISABLED);
        commentBean.setCommentRemark(remark);
        blogCommentMapper.update(commentBean,queryWrapper);
    }

    @Override
    public List<BlogCommentBean> queryBlogComment(String blogId) {
        QueryWrapper<BlogCommentBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("BLOG_ID",blogId);
        queryWrapper.eq("COMMENT_STATE",MessageConst.ENABLED);
        queryWrapper.orderByDesc("COMMENT_DATE");
        return blogCommentMapper.selectList(queryWrapper);
    }

    @Override
    public JSONObject examineComment(String content) {
        JSONObject jsonObject = new JSONObject();
        String res = this.textCensor(content);
        JSONObject parseRes = JSONUtil.parseObj(res);
        //审核结果类型，可取值1.合规，2.不合规，3.疑似，4.审核失败
        Integer conclusionType = parseRes.getInt("conclusionType");
        if(conclusionType != 1){
            JSONArray arrayData = JSONUtil.parseArray(parseRes.get("data"));
            for (Object arrayDatum : arrayData) {
                JSONObject errObj = JSONUtil.parseObj(arrayDatum);
                String msg = errObj.getStr("msg");
                jsonObject.put("code", ResultCode.FAIL.code);
                jsonObject.put("msg",msg);
            }
            return jsonObject;
        }else {
            jsonObject.put("code", ResultCode.SUCCESS.code);
            jsonObject.put("msg","审核通过");
            return jsonObject;
        }
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_LINK_CACHE,unless = "#result == null")
    public List<BlogLinkBean> queryBlogLinkList() {
        QueryWrapper<BlogLinkBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("LINK_STATE",MessageConst.ENABLED);
        queryWrapper.orderByDesc("LINK_DATE");
        queryWrapper.orderByDesc("LINK_WEIGHT");
        return blogLinkMapper.selectList(queryWrapper);
    }

    @Override
    public JSONObject insertBlogLink(BlogLinkBean blogLinkBean) {
        JSONObject jsonObject = new JSONObject();
        //解密
        String encryptKey = blogLinkBean.getEncryptKey();
        String linkUrl = AesUtil.deCode(blogLinkBean.getLinkUrl(), encryptKey);
        String linkName = AesUtil.deCode(blogLinkBean.getLinkName(), encryptKey);
        String linkImage = AesUtil.deCode(blogLinkBean.getLinkImage(), encryptKey);
        String linkDesc = AesUtil.deCode(blogLinkBean.getLinkDesc(), encryptKey);
        String linkEmail = AesUtil.deCode(blogLinkBean.getLinkEmail(), encryptKey);
        //入参校验
        if(ObjectUtil.isEmpty(blogLinkBean)) {
            jsonObject.put("errMsg","非法请求");
            return jsonObject;
        }
        if(StrUtil.isBlank(linkUrl)) {
            jsonObject.put("errMsg","请输入网站地址");
            return jsonObject;
        }
        if(StrUtil.isBlank(linkName)) {
            jsonObject.put("errMsg","请输入网站名称");
            return jsonObject;
        }
        if(StrUtil.isBlank(linkImage)) {
            jsonObject.put("errMsg","请输入网站图标地址");
            return jsonObject;
        }
        if(StrUtil.isBlank(linkDesc)) {
            jsonObject.put("errMsg","请输入网站描述");
            return jsonObject;
        }
        if(!ReUtil.isMatch(SysConstant.URL_REGEX,linkUrl)) {
            jsonObject.put("errMsg","请输入正确网站地址");
            return jsonObject;
        }
        if(!ReUtil.isMatch(SysConstant.URL_REGEX,linkImage)) {
            jsonObject.put("errMsg","请输入正确网站图标地址");
            return jsonObject;
        }
        if(StrUtil.isNotBlank(linkEmail) && !ReUtil.isMatch(SysConstant.EMAIL_REGEX,linkEmail)) {
            jsonObject.put("errMsg","请输入正确邮箱地址");
            return jsonObject;
        }
        //业务校验
        QueryWrapper<BlogLinkBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.like("LINK_URL",linkUrl);
        Integer count = blogLinkMapper.selectCount(queryWrapper);
        if(count > 0) {
            jsonObject.put("errMsg","请勿重复申请，如有疑问请通过首页邮件地址联系");
            return jsonObject;
        }
        //申请友链入库
        BlogLinkBean bean = new BlogLinkBean();
        String linkId = CommonUtil.genId();
        bean.setLinkId(linkId);
        bean.setLinkUrl(linkUrl);
        bean.setLinkName(linkName);
        bean.setLinkImage(linkImage);
        bean.setLinkDesc(linkDesc);
        bean.setLinkEmail(linkEmail);
        bean.setLinkState(MessageConst.DISABLED);
        bean.setLinkWeight(888);
        bean.setLinkDate(DateUtil.date());
        blogLinkMapper.insert(bean);
        //暂时人工审核，发送钉钉消息或者邮件告知
        log.info("--------->执行消息发送....");
        try {
            smsSendService.sendDingTextMsg("您有最新的友链申请，友链编码:【" + linkId + "】,请及时登录系统审核!",null,true);
        } catch (ApiException e) {
            log.error("--------->钉钉消息发送异常");
            e.printStackTrace();
        }


        return jsonObject;
    }

    @Override
    @Transactional
    public void insertBlogType(BlogTypeBean typeBean) {
        typeBean.setTypeId(CommonUtil.genId());
        typeBean.setTypeOrder(RandomUtil.randomInt(100));
        typeBean.setIsEnable(MessageConst.ENABLED);
        blogTypeMapper.insert(typeBean);
    }

    @Override
    @Transactional
    public void insertBlogTag(BlogTagBean tagBean) {
        tagBean.setTagId(CommonUtil.genId());
        tagBean.setTagState(MessageConst.ENABLED);
        blogTagMapper.insert(tagBean);
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_TIME_CACHE,unless = "#result == null")
    public JSONArray queryBlogTime() {
        JSONArray jsonArray = new JSONArray();
        //按月统计
        List<Map<String, Object>> mapList = this.blogStaticByMonth();
        if(IterUtil.isNotEmpty(mapList)) {
            for (Map<String, Object> map : mapList) {
                JSONObject jsonObject = new JSONObject();
                String blogDate = map.get("BLOG_DATE").toString();
                String blogCnt = map.get("BLOG_CNT").toString();
                jsonObject.put("blogDate",blogDate);
                jsonObject.put("blogCnt",blogCnt);
                List<BlogArchivBean> blogArchivList = this.queryBlogByDate(blogDate);
                jsonObject.put("blogArchivList",blogArchivList);
                jsonArray.add(jsonObject);
            }
        }
        return jsonArray;
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_MONTH_GROUP_CACHE,unless = "#result == null")
    public List<Map<String, Object>> blogStaticByMonth() {
        return commonBlogMapper.blogStaticByMonth();
    }

    @Override
    public List<BlogArchivBean> queryBlogByDate(String releaseDate) {
        List<BlogArchivBean> blogArchivList = new ArrayList<BlogArchivBean>();
        List<Map<String, Object>> mapList = commonBlogMapper.queryBlogByDate(releaseDate);
        for (Map<String, Object> map : mapList) {
            BlogArchivBean blogArchivBean = new BlogArchivBean();
            blogArchivBean.setBlogId(map.get("ID").toString());
            blogArchivBean.setBlogTitle(map.get("TITLE").toString());
            blogArchivBean.setReleaseDate(map.get("RELEASE_DATE").toString());
            blogArchivList.add(blogArchivBean);
        }
        return blogArchivList;
    }

    @Override
    @Cacheable(value = SysConstant.BLOG_BANNER_LIST_CACHE,unless = "#result == null")
    public List<BlogBannerBean> queryBannerList() {
        QueryWrapper<BlogBannerBean> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("IS_SHOW",MessageConst.ENABLED);
        queryWrapper.orderByDesc("BANNER_ORDER");
        queryWrapper.le("START_TIME",DateUtil.date()); //开始时间小于等于当前系统时间
        queryWrapper.ge("END_TIME",DateUtil.date());//结束时间大于等于当前系统时间
        return blogBannerMapper.selectList(queryWrapper);
    }

    @Override
    @Transactional
    public void insertBlogReply(BlogReplyBean replyBean) {
        replyBean.setReplyId(CommonUtil.genId());
        JSONObject jsonObject = this.examineComment(replyBean.getReplyContent());
        int code = jsonObject.getInt("code");
        String msg = jsonObject.getStr("msg");
        String url = "<a href=\"https://www.sunnyblog.top/detail.html?id="+replyBean.getBlogId()+"/\" target=\"_blank\">详情请点击</a>";
        if(code == ResultCode.FAIL.code) { //回复失败 ，邮件通知回复者
            replyBean.setReplyState(MessageConst.DISABLED);
            replyBean.setReplyRemark(msg);
            String content = "您的回复内容【"+replyBean.getReplyContent()+"】审核未通过,失败原因:" + msg + "," + url;
            smsSendService.sendMailNotice(userInfoService.queryUserById(replyBean.getReplyUserId()).getUserEmail(),content);
        }else {//回复内容合法，邮件通知评论者
            replyBean.setReplyState(MessageConst.ENABLED);
            replyBean.setReplyRemark(msg);
            String content = "您发布的评论有最新的回复:" + url;
            smsSendService.sendMailNotice(userInfoService.queryUserById(replyBean.getToUserId()).getUserEmail(),content);
        }
        replyBean.setReplyDate(DateUtil.date());
        blogReplyMapper.insert(replyBean);
    }


    /**
     * 获取API访问token
     * 该token有一定的有效期，需要自行管理，当失效时需重新获取.
     * @return assess_token 示例：
     * "24.460da4889caad24cccdb1fea17221975.2592000.1491995545.282335-1234567"
     */
    private String getAuth() {
        String getAccessTokenUrl = authUrl + "?"
                // 1. grant_type为固定参数
                + "grant_type=client_credentials"
                // 2. 官网获取的 API Key
                + "&client_id=" + apiKey
                // 3. 官网获取的 Secret Key
                + "&client_secret=" + securetKey;
        try {
            URL realUrl = new URL(getAccessTokenUrl);
            // 打开和URL之间的连接
            HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
            connection.setRequestMethod("GET");
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();
            // 定义 BufferedReader输入流来读取URL的响应
            BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String result = "";
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
            JSONObject jsonObject = new JSONObject(result);
            String access_token = jsonObject.getStr("access_token");
            return access_token;
        } catch (Exception e) {
            log.error("百度文字审核获取token失败！");
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 文字识别
     * @param text
     * @return
     */
    private String textCensor(String text) {
        Map<String,Object> map = new HashMap<>();
        map.put("access_token",this.getAuth());
        map.put("text", text);
        return HttpUtil.post(textCensor, map);
    }


}
